#ifndef __GLUE_INTR_H__
#define __GLUE_INTR_H__

#include <types.h>

/* Trap Numbers */

/* Processor-defined: */
#define T_DIVIDE                0	// divide error
#define T_DEBUG                 1	// debug exception
#define T_NMI                   2	// non-maskable interrupt
#define T_BRKPT                 3	// breakpoint
#define T_OFLOW                 4	// overflow
#define T_BOUND                 5	// bounds check
#define T_ILLOP                 6	// illegal opcode
#define T_DEVICE                7	// device not available
#define T_DBLFLT                8	// double fault
// #define T_COPROC             9   // reserved (not used since 486)
#define T_TSS                   10	// invalid task switch segment
#define T_SEGNP                 11	// segment not present
#define T_STACK                 12	// stack exception
#define T_GPFLT                 13	// general protection fault
#define T_PGFLT                 14	// page fault
// #define T_RES                15  // reserved
#define T_FPERR                 16	// floating point error
#define T_ALIGN                 17	// aligment check
#define T_MCHK                  18	// machine check
#define T_SIMDERR               19	// SIMD floating point error

/* Hardware IRQ numbers. We receive these as (IRQ_OFFSET + IRQ_xx) */
#define IRQ_OFFSET              32	// IRQ 0 corresponds to int IRQ_OFFSET

#define IRQ_TIMER               0
#define IRQ_KBD                 1
#define IRQ_COM1                4
#define IRQ_IDE1                14
#define IRQ_IDE2                15
#define IRQ_ERROR               19
#define IRQ_SPURIOUS            31

/* registers as pushed by pushal */
struct pushregs {
	uint32_t reg_edi;
	uint32_t reg_esi;
	uint32_t reg_ebp;
	uint32_t reg_oesp;	/* Useless */
	uint32_t reg_ebx;
	uint32_t reg_edx;
	uint32_t reg_ecx;
	uint32_t reg_eax;
};

struct trapframe {
	struct pushregs tf_regs;
	uint16_t tf_es;
	uint16_t tf_padding1;
	uint16_t tf_ds;
	uint16_t tf_padding2;
	uint32_t tf_trapno;
	/* below here defined by x86 hardware */
	uint32_t tf_err;
	uintptr_t tf_eip;
	uint16_t tf_cs;
	uint16_t tf_padding3;
	uint32_t tf_eflags;
	/* below here only when crossing rings, such as from user to kernel */
	uintptr_t tf_esp;
	uint16_t tf_ss;
	uint16_t tf_padding4;
} __attribute__ ((packed));

void idt_init(void);
void print_trapframe(struct trapframe *tf);
void print_regs(struct pushregs *regs);
bool trap_in_kernel(struct trapframe *tf);

#define local_intr_enable_hw  do { __asm __volatile ("sti"); } while (0)
#define local_intr_disable_hw do { __asm __volatile ("cli"); } while (0)

#define local_intr_save_hw(x)      do { (x) = (read_eflags() & FL_IF) != 0; cli(); } while (0)
#define local_intr_restore_hw(x)   do { if (x) sti(); } while (0)

#endif /* !__GLUE_INTR_H__ */
